package cachebase

import (
	"context"
	"encoding/json"
	"fmt"
	"huijing_mall/internal/database/models"
	"huijing_mall/variable"
	"time"

	"github.com/redis/go-redis/v9"

	"huijing_mall/pkg/logger"
)

func RedisSet(rdb *redis.Client, key string, value interface{}) error {
	data, _ := json.Marshal(value)
	_, err := rdb.Set(context.Background(), key, data, 30*time.Minute).Result()
	if err != nil {
		return err
	}
	return nil
}

func RedisSetKeepTTL(rdb *redis.Client, key string, value interface{}) error {
	data, _ := json.Marshal(value)
	// Lua 脚本：先获取 TTL，再 SET 并恢复 TTL
	script := `
    local ttl = redis.call("TTL", KEYS[1])  -- 使用 redis.call 而不是 cachebase.call
    redis.call("SET", KEYS[1], ARGV[1])
    if ttl > 0 then
        redis.call("EXPIRE", KEYS[1], ttl)
    end
    return ttl
	`
	// 执行脚本
	ttl, err := rdb.Eval(context.Background(), script, []string{key}, data).Int()

	//_, err := rdb.Set(context.Background(), key, data, cachebase.KeepTTL).Result()
	if err != nil {
		return err
	}
	logger.Info(fmt.Sprintf("Updated key with TTL:%v", ttl))
	return nil
}

func RedisSetUserData(rdb *redis.Client, key string, value models.User, keepTime time.Duration) error {
	data, _ := json.Marshal(value)
	_, err := rdb.Set(context.Background(), key, data, keepTime*time.Second).Result()
	if err != nil {
		return err
	}
	return nil
}

func RedisGet(rdb *redis.Client, key string) (string, error) {
	res, err := rdb.Get(context.Background(), key).Result()
	if err != nil {
		return "", err
	}
	return res, nil
}

func RedisIncr(rdb *redis.Client, key string) {
	_, err := rdb.Incr(context.Background(), key).Result()
	if err != nil {
		fmt.Println(err)
		return
	}
	return
}

func RedisExpireat(rdb *redis.Client, key string) error {

	// 获取当前时间
	now := time.Now()

	// 计算今日零点的时间
	midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())

	// 计算明日零点的时间
	nextMidnight := midnight.Add(24 * time.Hour)

	_, err := rdb.ExpireAt(context.Background(), key, nextMidnight).Result()
	if err != nil {
		return err
	}
	return nil
}

func RedisTimeThree(rdb *redis.Client, key, value string) error {
	_, err := rdb.Set(context.Background(), key, value, 30*time.Minute).Result()
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func RdKeepToken(rdb *redis.Client, key, value string, keepTime time.Duration) error {
	_, err := rdb.Set(context.Background(), key, value, keepTime*time.Second).Result()
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func RedisTimeTwo(rdb *redis.Client, key, value string) error {
	_, err := rdb.Set(context.Background(), key, value, 20*time.Minute).Result()
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func RedisExist(rdb *redis.Client, key string) bool {
	res := rdb.Exists(context.Background(), key)
	if res.Err() != nil {
		return false
	}
	if res.Val() != 1 {
		return false
	}
	return true
}

// 删除 key
func RedisDel(rdb *redis.Client, key string) bool {
	res := rdb.Del(context.Background(), key)
	if res.Err() != nil {
		fmt.Println(res.Err())
		return false
	}
	//fmt.Println(echo.Val())
	if res.Val() != 1 {
		return false
	}
	return true
}

func GetRedisCode(rdb *redis.Client, key string) string {
	result, err := rdb.Get(context.Background(), key).Result()
	if err != nil {
		return ""
	}
	return result
}

func RedisCodeTime(rdb *redis.Client, key, value string, minute time.Duration) error {
	_, err := rdb.Set(context.Background(), key, value, minute*time.Minute).Result()
	if err != nil {
		return err
	}
	return nil
}

func LPushList(rdb *redis.Client, key, value string) error {
	_, err := rdb.LPush(context.Background(), key, value).Result()
	if err != nil {
		return err
	}
	//fmt.Println(cmd)
	return nil
}

func LGetList(rdb *redis.Client, key string) (data string, err error) {
	cmd, err := rdb.LPop(context.Background(), key).Result()
	if err != nil {
		return "", err
	}
	return cmd, nil
}

// AddToZSet 向有序集合添加元素
func AddToZSet(rdb *redis.Client, key string, value string, priority float64) error {
	err := rdb.ZAdd(context.Background(), key, redis.Z{Score: priority, Member: value}).Err()
	if err != nil {
		return fmt.Errorf("ZADD failed: %v", err)
	}
	return nil
}

// AddToZSetWithDefaultScore 向有序集合添加元素（使用默认 score）
func AddToZSetWithDefaultScore(rdb *redis.Client, key string, value string) error {
	err := rdb.ZAdd(context.Background(), key, redis.Z{Score: variable.DefaultScore, Member: value}).Err()
	if err != nil {
		logger.Error(fmt.Sprintf("ZADD failed: %v", err))
		return fmt.Errorf("ZADD failed: %v", err)
	}
	return nil
}

// GetZSetRange 获取有序集合中的元素（按优先级排序）
func GetZSetRange(rdb *redis.Client, key string, start, stop int64) ([]string, error) {
	result, err := rdb.ZRange(context.Background(), key, start, stop).Result()
	if err != nil {
		return nil, fmt.Errorf("ZRANGE failed: %v", err)
	}
	return result, nil
}

// GetNextElement 逐个获取有序集合中的元素
func GetNextElement(rdb *redis.Client, key string, start int64) (string, int64, error) {
	// 每次获取一个元素
	result, err := rdb.ZRange(context.Background(), key, start, start).Result()
	if err != nil {
		return "", start, fmt.Errorf("ZRANGE failed: %v", err)
	}
	if len(result) == 0 {
		return "", start, fmt.Errorf("no more elements")
	}
	// 返回当前元素和下一个游标
	return result[0], start + 1, nil
}

// RemoveFromZSet 从有序集合中删除元素
func RemoveFromZSet(rdb *redis.Client, key string, value string) error {
	err := rdb.ZRem(context.Background(), key, value).Err()
	if err != nil {
		return fmt.Errorf("ZREM failed: %v", err)
	}
	return nil
}
